#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>

#include <stdio.h>
#include <string.h>
#include <GL/glut.h>

#define VIEWPORT_WIDTH 640
#define VIEWPORT_HEIGHT 480
#define KEY_Q 113

GLvoid InitGL();
GLvoid OnDisplay();
GLvoid OnReshape(GLint w, GLint h);
GLvoid OnKeyPress(unsigned char key, GLint x, GLint y);
GLvoid OnIdle();

CvCapture* g_Capture;
GLint g_hWindow;

int main(int argc, char* argv[])
{
  //Create window
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  glutInitWindowSize(VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
  
  g_hWindow = glutCreateWindow("Video Texture");
  
  //Init Camera
  g_Capture = cvCreateCameraCapture(0);
  if (!g_Capture){
    printf("Unable to init camera capture!!!");
    return 1;
  }
  
  //Initial openGL
  InitGL();

  glutMainLoop();
  
  return 0;
}

GLvoid InitGL()
{
  glClearColor(0.0, 0.0, 0.0, 0.0);

  glutDisplayFunc(OnDisplay);
  glutReshapeFunc(OnReshape);
  glutKeyboardFunc(OnKeyPress);
  glutIdleFunc(OnIdle);
}

GLvoid OnDisplay()
{
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glEnable(GL_TEXTURE_2D);

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluOrtho2D(0, VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 0);

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

  glBegin(GL_QUADS);
  glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f);
  glTexCoord2f(1.0f, 0.0f); glVertex2f(VIEWPORT_WIDTH, 0.0f);
  glTexCoord2f(1.0f, 1.0f); glVertex2f(VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
  glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, VIEWPORT_HEIGHT);
  glEnd();

  glFlush();
  glutSwapBuffers();
}

GLvoid OnReshape(GLint w, GLint h)
{
  glViewport(0, 0, w, h);
}

GLvoid OnKeyPress(unsigned char key, int x, int y)
{
  switch(key){
  case KEY_Q:
    cvReleaseCapture(&g_Capture);
    glutDestroyWindow(g_hWindow);
    exit(0);
    break;
  }
  glutPostRedisplay();
}

GLvoid OnIdle()
{
  IplImage *image = cvQueryFrame(g_Capture);

  cvCvtColor(image, image, CV_BGR2RGB);
  
  gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, image->width, image->height, GL_RGB, GL_UNSIGNED_BYTE, image->imageData);
  
  glutPostRedisplay();
}
    
